#pragma once

#include "Common.h"
#include "FixedLengthpool.h"
#include "PageMap.h"

#ifdef _WIN64 // WIN64
typedef TCMalloc_PageMap3<64 - PAGE_SHIFT> TCMalloc_PageMap;
#elif _WIN32 // WIN32
typedef TCMalloc_PageMap2<32 - PAGE_SHIFT> TCMalloc_PageMap;
#elif __LP64__ // linux64位
typedef TCMalloc_PageMap3<64 - PAGE_SHIFT> TCMalloc_PageMap;
#else  // linux32位
typedef TCMalloc_PageMap2<32 - PAGE_SHIFT> TCMalloc_PageMap;
#endif


class PageCache
{
public:
	static PageCache* GetInstance() { return &_Inst; }

	Span* GetSpan(size_t k); 

	// map里面是加了页锁的，所以调用前要确保页锁状态为unlock
	Span* MapBlockToSpan(void* block);

	void ReleaseSpanToPageCache(Span* span);

	std::mutex _page_mtx; // 页锁

private:
	void AdjustMapAndSpan(Span* span, size_t k);

	PageCache() {}

	PageCache(const PageCache&) = delete;
	PageCache& operator==(const PageCache&) = delete;

	SpanList _pagelist[NPAGES]; // 根据页的数量映射

	// std::unordered_map<PAGE_ID, Span*> _IdSpanMap; // ID和span*的映射关系
	// 如果span分配给了central池，则会建立每一个ID和span*的映射关系
	// 如果span未被使用，还在page池中，则建立span的起始ID、结束ID和page*的映射关系
	// 这个map由page池维护
	//TCMalloc_PageMap2<32 - PAGE_SHIFT> _IdSpanMap;
	//TCMalloc_PageMap3<64 - PAGE_SHIFT> _IdSpanMap;
	TCMalloc_PageMap _IdSpanMap; 

	kele::blockectPool<Span> _span_pool;

	static PageCache _Inst;
};